/*
** 
DOM API reference: http://docs.oracle.com/cd/E16338_01/appdev.112/e10770/dom.htm
*/

#include <stdio.h>
 
#ifndef XML_ORACLE
# include <xml.h>
#endif
 
#define DOCUMENT "xmldemo.xml"

void dumpnode( xmlctx* xtcx, xmlnode* node);
void dumpret( xmlerr ret);
void iterate( xmlctx *xctx, xmliter *iter, boolean forward);
void treewalk( xmlctx* xctx, xmlwalk* walker);
void rangeoper( xmlctx* xctx, xmlrange* rangep, xmlnode* node);

int main()
{
    xmlctx*     xctx;
    xmldocnode* doc;
    xmlnode*    nodep;
    xmlerr      ecode;

    puts( "XML DOM Traversal Range sample");
 
    puts( "Initializing XML package...");
 
    if (!(xctx = XmlCreate(&ecode, (oratext *) "traverse_xctx", NULL)))
    {
	printf( "Failed to create XML context, error %u\n", (unsigned) ecode);
	return 1;
    }

    printf( "Parsing '%s' ...\n", DOCUMENT);
    if (!(doc = XmlLoadDom(xctx, &ecode, "file", DOCUMENT, "validate", TRUE,
			   "discard_whitespace", TRUE, NULL)))
    {
	printf( "Parse failed, error %u\n", (unsigned) ecode);
	return 1;
    }

    nodep = XmlDomGetDocElem( xctx, doc);
    printf("Name of root node is: %s\n", XmlDomGetNodeName(xctx, nodep));
    printf("Name of first child: %s\n", XmlDomGetNodeName(xctx, XmlDomGetFirstChild(xctx, nodep)));
    printf("Name of child of first child: %s\n", XmlDomGetNodeValue(xctx, XmlDomGetFirstChild(xctx, XmlDomGetFirstChild(xctx, nodep))));

#if 0
    puts( "Iteration of the DOM tree");

    iterp = XmlDomCreateNodeIter( xctx, &iter, nodep,
				  XMLDOM_SHOW_ALL, NULL, FALSE);
    iterate( xctx, iterp, TRUE);
    iterate( xctx, iterp, FALSE);

    puts( "Tree walk of the DOM tree");

    walkp = XmlDomCreateTreeWalker( xctx, &walk, nodep,
				    XMLDOM_SHOW_ALL, NULL, FALSE);
    treewalk( xctx, walkp);

    puts( "Range manipulations of the DOM tree");

    rangep = XmlDomCreateRange( xctx, &range, doc);

    rangeoper( xctx, rangep, nodep);

    XmlFreeDocument( xctx, doc);
    XmlDestroy( xctx);
#endif

    return 0;
}

void iterate( xmlctx* xctx, xmliter* iter, boolean forward)
{
    xmlnode* node;
    xmlerr   reti;

    while (node = (forward ? XmlDomIterNextNode(xctx, iter, &reti) :
			     XmlDomIterPrevNode(xctx, iter, &reti)))
      dumpnode( xctx, node);
    dumpret( reti);
}

void treewalk( xmlctx* xctx, xmlwalk* walker)
{
    xmlnode* node;
    xmlnode* root;
    xmlerr   retw;

    root = walker->cur_xmliter;
    dumpnode( xctx, root);

    node = XmlDomWalkerFirstChild( xctx, walker, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerNextSibling( xctx, walker,&retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerPrevSibling( xctx, walker, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerParentNode( xctx, walker, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerLastChild( xctx, walker, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerGetCurrentNode( xctx, walker, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }
    node = XmlDomWalkerSetCurrentNode( xctx, walker, root, &retw);
    if (retw == XMLERR_OK)
      dumpnode( xctx, node);
    else
    {
      dumpret( retw);
      return;
    }

    while (node = XmlDomWalkerNextNode( xctx, walker, &retw))
	dumpnode( xctx, node);

    while (node = XmlDomWalkerPrevNode( xctx, walker, &retw))
	dumpnode( xctx, node);

    dumpret( retw);
}

void rangeoper( xmlctx* xctx, xmlrange* rangep, xmlnode* node)
{
    xmlerr retw;
    xmlnode* new_node;

    retw = XmlDomRangeSetEnd( xctx, rangep, node, 1);
    dumpret( retw);

    retw = XmlDomRangeSetStart( xctx, rangep, node, 0);
    dumpret( retw);

    new_node = XmlDomRangeCloneContents( xctx, rangep, &retw);
    dumpret( retw);

    dumpnode( xctx, new_node);

    printf( "Demo end\n");
}

void dumpnode( xmlctx* xctx, xmlnode* node)
{
  char*    str;

  switch (XmlDomGetNodeType(xctx, node))
  {
  case XMLDOM_FRAG:
    puts( "    Fragment");
    break;
  case XMLDOM_ELEM:
    str = (char*)XmlDomGetNodeName( xctx, node);
    printf( "    Element: %s\n", str);
    break;
  case XMLDOM_COMMENT:
    str = (char*)XmlDomGetNodeValue( xctx, node);
    printf( "    Comment: %s\n", str);
    break;
  case XMLDOM_TEXT:
    str = (char*)XmlDomGetNodeValue( xctx, node);
    printf( "    Text: %s\n", str);
    break;
  }
}

void dumpret( xmlerr ret)
{
    switch (ret)
    {
        case XMLERR_OK:
	    puts( "    O.K.");
	    break;
        case XMLERR_ITER_NULL:
	    puts( "    Iterator is NULL");
	    break;
        case XMLERR_ITER_DETACHED:
	    puts( "    Iterator is detached");
	    break;
        case XMLERR_ITER_CUR_REMOVED:
	    puts( "    Iterator current node is removed");
	    break;
        case XMLERR_WALKER_NULL:
	    puts( "    Walker is NULL");
	    break;
        case XMLERR_WALKER_NODE_PAR_NULL:
	    puts( "    Walker: node parameter is NULL");
	    break;
        case XMLERR_WALKER_BAD_NEW_CUR:
	    puts( "    Walker: new current node is not under root");
	    break;
        case XMLERR_WALKER_BAD_NEW_ROOT:
	    puts( "    Walker: current node is not under new root");
	    break;
        case XMLERR_RANGE_NULL:
	    puts( "    XMLERR_RANGE_NULL");
	    break;
        case XMLERR_RANGE_DETACHED:
	    puts( "    XMLERR_RANGE_DETACHED");
	    break;
        case XMLERR_RANGE_BAD_NODE:
	    puts( "    XMLERR_RANGE_BAD_NODE");
	    break;
        case XMLERR_RANGE_BAD_INDEX:
	    puts( "    XMLERR_RANGE_BAD_INDEX");
	    break;
        case XMLERR_RANGE_BAD_DOC:
	    puts( "    XMLERR_RANGE_BAD_DOC");
	    break;
        case XMLERR_RANGE_START_AFTER_END:
	    puts( "    XMLERR_RANGE_START_AFTER_END");
	    break;
        case XMLERR_RANGE_NO_ROOT:
	    puts( "    XMLERR_RANGE_NO_ROOT");
	    break;
        case XMLERR_RANGE_DIFF_ROOTS:
	    puts( "    XMLERR_RANGE_DIFF_ROOTS");
	    break;
        case XMLERR_RANGE_NO_ANCESTOR:
	    puts( "    XMLERR_RANGE_NO_ANCESTOR");
	    break;
        case XMLERR_RANGE_NONE:
	    puts( "    XMLERR_RANGE_NONE");
	    break;
        case XMLERR_RANGE_COLLAPSE:
	    puts( "    XMLERR_RANGE_COLLAPSE");
	    break;
        case XMLERR_RANGE_ERROR:
	    puts( "    XMLERR_RANGE_ERROR");
	    break;
	default:
	    puts( "    ???");
	    break;
    }
}

/* end of file Traverse.c */

